﻿using Api.DevOpsManage.App_Start;
using DevOps.Logic;
using Common.Model;
using Container.Library;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Serialize.Library;
using System.Collections.Generic;
using Validate.Library;

/*
* 命名空间: Api.DevOpsManage.Areas.Authority.Controllers
*
* 功 能： 岗位接口控制器
*
* 类 名： LoginController
*
* Version   变更日期            负责人     变更内容
* ─────────────────────────────────────────────────
* V1.0.1    2020/03/17 14:34:43 Harvey     创建
*
* Copyright (c) 2020 Harvey Corporation. All rights reserved.
*/
namespace Api.DevOpsManage.Areas.Admin.Controllers
{
    /// <summary>
    /// 登录界面相关接口
    /// </summary>
    [ApiExplorerSettings(GroupName = "Login")]
    [Route("api/[controller]")]
    [ApiController]
    public class LoginController : BaseApiController
    {
        private readonly ISysUserService userService = null;

        private readonly IJwtFactory jwtFactoryObj = null;
        private readonly JwtIssuerOptions jwtOptionsObj = null;

        /// <summary>
        /// 登录相关接口控制器构造函数
        /// </summary>
        public LoginController(IJwtFactory jwtFactory, IOptions<JwtIssuerOptions> jwtOptions)
        {
            //用户管理逻辑注入
            userService = UnityCIContainer.Instance.GetService<ISysUserService>();
            //Jwt操作逻辑
            jwtFactoryObj = jwtFactory;
            //Jwt配置信息
            jwtOptionsObj = jwtOptions.Value;
        }

        /// <summary>
        /// 获取验证码
        /// </summary>
        /// <param name="uniqueIdentifier">
        /// 客户端请求物理机唯一标识符【WEB/CS桌面获取物理机MAC地址；中转服务，获取请求客户端的唯一信息】
        /// </param>
        /// <remarks>
        /// 客户端请求物理机唯一标识符：可以在客户端生成一个可以保存5分钟或永久保存的GUID
        /// 验证码有效期：5分钟
        /// </remarks>
        /// <returns></returns>
        [HttpGet("LoadValidateCode/{uniqueIdentifier}")]
        [ClientApiFilter(DeviceType.PCBack, false)]
        public ResultFileInfo LoadValidateCode(string uniqueIdentifier)
        {
            var resultInfo = new ResultFileInfo();

            TryCatch(() =>
            {
                resultInfo = userService.LoadValidateCode(uniqueIdentifier);

            }, ex =>
            {
                resultInfo.SystemExc(resultInfo, ex, "获取验证码信息失败");

            }, $"系统错误，登录界面-获取验证码信息失败");

            return resultInfo;
        }

        /// <summary>
        /// 获取验证码，返回二进制信息【注意：这个拿来做测试，正式的用LoadValidateCode】
        /// </summary>
        /// <param name="uniqueIdentifier">客户端请求物理机唯一标识符【WEB/CS桌面获取物理机MAC地址；中转服务，获取请求客户端的唯一信息】</param>
        /// <returns></returns>
        [HttpGet("LoadValidateCodeToPic/{uniqueIdentifier}")]
        [ClientApiFilter(DeviceType.PCBack, false)]
        public FileContentResult LoadValidateCodeToPic(string uniqueIdentifier)
        {
            var resultInfo = new ResultFileInfo();

            TryCatch(() =>
            {
                resultInfo = userService.LoadValidateCode(uniqueIdentifier);

            }, ex =>
            {
                resultInfo.SystemExc(resultInfo, ex, "获取验证码信息失败");

            }, $"系统错误，登录界面-获取验证码信息失败");

            return File(resultInfo.FileContents, resultInfo.ContentType);
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="loginInfo"></param>
        /// <remarks>
        /// 客户端请求物理机唯一标识符：LoadValidateCode传递的uniqueIdentifier
        /// 
        ///返回Code情况：
        /// 1、操作成功 返回1000
        /// 2、如果密码错误、验证码不正确、用户已被冻结，返回 1205，无效操作
        /// 3、如果验证码失效，返回1103
        /// 4、缓存用户信息失败，返回3000
        /// 5、账号不存在 ，返回1201
        /// </remarks>
        /// <returns> 
        /// </returns>
        [HttpPost("LoginCheck")]
        [ClientApiFilter(DeviceType.PCBack, false)]
        public ResultJsonInfo<UserLoginInfo> LoginCheck([FromBody]UserInfoLoginRequest loginInfo)
        {
            var resultInfo = new ResultJsonInfo<UserLoginInfo>();

            TryCatch(() =>
            {
                loginInfo.Validate();
                resultInfo = userService.UserLogin(loginInfo);

                if (resultInfo.Code == ActionCodes.Success)
                {
                    var userInfo = JsonHelper.ToJson(resultInfo.Data).JsonToObject<Dictionary<string, object>>();
                    var claimsIdentity = jwtFactoryObj.GenerateClaimsIdentity(userInfo);
                    var token =  jwtFactoryObj.GenerateEncodedToken(resultInfo.Data.name, resultInfo.Data.token, claimsIdentity).GetAwaiter().GetResult();
                    resultInfo.Data.token = token;
                }
            }, ex =>
            {
                resultInfo.SystemExc(resultInfo, ex, "用户登录失败");

            }, $"系统错误，登录界面-用户登录失败");

            return resultInfo;
        }

        /// <summary>
        /// 刷新Token
        /// </summary>
        /// <remarks>
        /// 返回Code情况：
        /// 1、操作成功 返回1000
        /// 2、缓存用户信息失败，返回3000
        /// 3、用户已被冻结，返回1205，无效操作
        /// 4、账号不存在 ，返回1201
        /// 5、RefreshToken无效，请重新登录 ，返回1102
        /// </remarks>
        /// <param name="refreshTokenInfo"></param>
        /// <returns></returns>
        [HttpPost("RefreshToken")]
        [ClientApiFilter(DeviceType.PCBack, false)]
        public ResultJsonInfo<UserLoginInfo> RefreshToken([FromBody]UserInfoRefreshTokenRequest refreshTokenInfo)
        {
            var resultInfo = new ResultJsonInfo<UserLoginInfo>();

            TryCatch(() =>
            {
                refreshTokenInfo.Validate();
                resultInfo = userService.LoadUserInfoByRefreshToken(refreshTokenInfo);
                if (resultInfo.Code == ActionCodes.Success)
                {
                    var userInfo = JsonHelper.ToJson(resultInfo.Data).JsonToObject<Dictionary<string, object>>();
                    var claimsIdentity = jwtFactoryObj.GenerateClaimsIdentity(userInfo);
                    var token = jwtFactoryObj.GenerateEncodedToken(resultInfo.Data.name, resultInfo.Data.token, claimsIdentity).GetAwaiter().GetResult();

                    resultInfo.Data.token = token;
                }
            }, ex =>
            {
                resultInfo.SystemExc(resultInfo, ex, "刷新Token失败");

            }, $"系统错误，登录界面-刷新Token失败");

            return resultInfo;
        }
    }
}